Containers are views which may contain other (embedded) views. Typically, containers belong to one of two categories. The first category contains containers with a fixed structure and fixed types of the embedded views. For example, an e-mail container view may consist of exactly two views: a toolbar view at the top, and a text view below. The layout of these views typically cannot be edited. Such views are called static containers.
The second category of containers can embed arbitrary numbers of views, which can be of arbitrary types. Text views and form views are typical examples of such dynamic container views. Only this second category of container views, called dynamic containers, is supported by module Containers, and it is the topic of this text.
Dynamic containers consist of a variable number of embedded views, plus some intrinsic contents. Text views for example have text as their intrinsic contents, but also allow to let arbitrary views (i.e. non-intrinsic contents) flow along in the text. Form views are degenerated in the sense that they provide no intrinsic contents of their own.
Different compound document standards (OLE, OpenDoc) differ in the way they treat selections and the focus. The focus is the currently edited view, the view which receives keyboard events, the view which determines the currently available menus, the view which contains the currently relevant selection, caret, or other mark.
Containers provides the building blocks for container views, including special container models and container controllers. Other than most Oberon/F modules, Containers exports several partially implemented types, rather than pure interface types. What is implemented is provided in a form suitable for the used platform, i.e. user interface differences are hidden by the implementation of Containers.
In particular, Containers fully implements singleton selections, i.e. selections which cover exactly one view and no intrinsic contents. Such selections are subject to special operations and require platform-dependent treatment. Also, Containers implements the focus concept: a single embedded view within a controller's model that is picked by the user as current focus.
Example:
subsystem
CONST noSelection, noFocus, noCaret
Possible elements of Controller.opt. noSelection denotes that selections should be switched off, noFocus denotes that no embedded view should be allowed to become focus, and noCaret denotes that the caret (insertion mark) and thus the possibility to type or paste should be switched off.
CONST mask, layout
Two particularly useful subsets of Controller.opt. A mask prevents editing of the container's intrinsic contents, but enables focusing and thereby editing of the contained objects; for example, this allows to use a form without changing the form itself. A layout does just the opposite: focusing and therefore editing of contained objects is inhibited, but the container's intrinsic contents may be freely edited; for example, this is useful when editing a form without wanting to actually activate, say, a button, while editing its position in the form.
CONST deselect, select
Possible values of the select parameter of Controller.SelectAll.
CONST any, selection
Possible values of the selection parameters of Controller.GetFirstView, Controller.GetNextView, Controller.GetPrevView, Controller.PollNativeProp, and Controller.SetNativeProp. Controls whether the range of the operation is the current selection or the whole container contents.
CONST hide, show
Possible values of the show parameter of FadeMarks, MarkSingleton, Controller.Mark, Controller.MarkCaret, Controller.MarkDropTarget, Controller.MarkPickTarget, and Controller.MarkSelections. Controls whether the respective mark is to be hidden or shown.
Return minimum (minW, minH) and maximum (maxW, maxH) bounds on view sizes to be embedded in model m. If it is tried to embed a view into m with width < minW, width >= maxW, height < minH, or height >= maxH, then m should (but is not absolutely required to) modify the size of the embedded view in order to make it fit.
In-place substitution of view old which must be embedded in m by view new which must not yet be embedded anywhere. As a result, new gets embedded in m, but old retains its context which it then shares with new. Replacing a view in
place allows wrapping of views: A new view takes place of an existing one, adds some new properties, but still can hold a reference to the old view and delegate requests to the old view. Since the old view has maintained its context, it will continue to function as if it where directly embedded in m.
Fully implements internalization for views without intrinsic persistent state by handling internalization of the container view's model and controller. If the model internalization fails, the view is turned into an alien and internalization of v is cancelled; otherwise the model is attached to v. If the controller internalization fails, the controller is kept for later externalization to prevent loss of information, but is otherwise not connected to the view (v.ThisController() = NIL), and the view is internalized normally (i.e. not turned into an alien).
Fully implements externalization for views without intrinsic persistent state by handling externalization of the container view's model and controller. If v has been internalized before with an alien controller, and no other controller has been installed thereafter, then the alien controller will be externalized, although v.ThisController() = NIL.
v.ThisModel() # NIL 20
PROCEDURE (v: View) CopyFrom (source: Views.View)
Assuming that the model of v has already been established, copy the controller and possibly other view state from source. If source holds a hidden alien controller (cf. Internalize above), a reference to it is also copied.
For display in frame f, determine the bounding box of view which must be a view contained in v. Should the computation of the bounding box be too expensive, returning an approximation is acceptable.
If v has a controller installed, then the default is to delegate to the controller, i.e. to call v.ThisController().RestoreMarks(f, l, t, r, b). Otherwise nothing is done by default.
PROCEDURE (v: View) Neutralize
Default, Extension
If v has a controller installed, then the default is to delegate to the controller, i.e. to call v.ThisController().Neutralize. Otherwise nothing is done by default.
If v has a controller installed, then the default is to delegate to the controller, i.e. to call v.ThisController().ConsiderFocusRequestBy(view). Otherwise nothing is done by default.
First calls v.CatchModelMsg(msg), then, if v has a controller installed, calls v.ThisController().HandleModelMsg(msg). That is, the view sees the model message msg before its controller does.
PROCEDURE (v: View) HandleViewMsg (f: Views.Frame; VAR msg: Views.Message)
Default, Extension
First calls v.CatchViewMsg(msg), then, if v has a controller installed, calls v.ThisController().HandleViewMsg(msg). That is, the view sees the view message msg before its controller does.
VAR msg: Controllers.Message; VAR focus: Views.View)
Default, Extension
If v has a controller installed, calls v.ThisController().HandleCtrlMsg(f, msg, focus), then calls v.CatchCtrlMsg(f, msg, focus). That is, the controller sees the controller message msg before the view does.
Additionally, a strict filter is applied to throw away unwanted messages: Messages are only delegated to the controller or view if they fulfill one of the following three criteria:
First, the frame f is a target or front frame. Second, the message is derived from Controllers.PollOpsMsg, Controllers.PollCursorMsg, Controllers.TransferMessage, or Controllers.PageMsg. Third, the context of v is normalizing, i.e. v.context.Normalize() holds, and the message is derived from Controllers.PollSectionMsg or Controllers.ScrollMsg. This is a standard message filtering condition making components more robust against spurious message sends.
Finally, scrolling messages (derived from Controllers.PollSectionMsg or Controllers.ScrollMsg) may ask for shallow handling (~msg.focus), i.e. supression of forwarding to a possibly existing subfocus. This is generically handled by clearing focus on return in these cases.
(msg IS Controllers.PollSectionMsg) OR (msg IS Controllers.ScrollMsg)
First calls v.CatchPropMsg(p), then, if v has a controller installed, calls v.ThisController().HandlePropMsg(p). That is, the view sees the property message p before its controller does.
TYPE Controller
Interface, Extension
Controllers for containers.
opts-: SET
Option set of controller; used to restrict controller functionality to defined subsets.
PROCEDURE (c: Controller) ThisView (): View
Return type is narrowed.
PROCEDURE (c: Controller) SetOpts (opts: SET)
Base, Operation
Set the options of c. This is only an operation after a view has been installed, i.e. c.ThisView() # NIL, otherwise it is a simple assignment of opts to c.opts. Options 0..7 are used or reserved by Oberon/F, the rest may be used by extensions.
Set the properties of c's native selected or whole contents to p, irrespective of possible embedded views in that range. For properties also in old change only those property values of c that match the ones given in old. This allows for masked modification of properties. For example, in a colored model, all red objects could be changed to become green.
PROCEDURE (c: Controller) GetFirstView (selection: BOOLEAN; VAR v: Views.View)
Interface
Get the first view embedded in c's model, relative to the model's start or that of a possible selection.
PROCEDURE (c: Controller) GetNextView (selection: BOOLEAN; VAR v: Views.View)
Interface
Get the next view in the specified range, which is either the selected or the whole contents of c's model. The next view of the last view in the range is NIL.
PROCEDURE (c: Controller) GetPrevView (selection: BOOLEAN; VAR v: Views.View)
Default
Get the previous view in the specified range, which is either the selected or the whole contents of c's model. The default uses GetFirstView and GetNextView to seek the previous view of v. The previous view of the first view in the range is NIL.
Return whether the material being dragged could be dropped into frame f at its local coordinate (x, y). The default is to accept any drop request, i.e. to return TRUE.
Mark the drop target in destination frame dst at point (dx, dy) for a potential dropping of material from source frame src, origin (sx, sy). show determines whether the mark should be drawn or removed. isSingle determines whether the selection to be dropped is a singleton.
Drop the material being dragged from source frame src, origin (sx, sy) and encapsulated in view under control of c in destination frame dst at point (dx, dy). The default is to ignore the drop. isSingle determines whether the selection to be dropped is a singleton.
Mark the drop target in destination frame dst at point (dx, dy) for a potential dropping of material from source frame src, origin (sx, sy). show determines whether the mark should be drawn or removed. The default is not to mark at all.
Track marks in frame f starting at point (x, y) as specified by units, extend, and add. Marks are general selections and insertion points (carets). Tracking of larger logical units (e.g. words instead of characters) is requested by units. Continuous extension of an existing selection is requested by extend. Discontinuous addition to an existing selection is requested by add.
Some controllers may ignore one or the other request, e.g. may not distinguish units of varying granularity, may not support multiple selected objects, or may not support discontinuous selections.
Request to resize view, which must be embedded in c's model, to the size given by rectangle (l, t, r, b).
(Typically, a controller delegates this request to its model which implements the request by using Properties.PreferredSize to negotiate the new size with view.)
Return the bounding box of the selection, by giving its top-left reference point and its width and height. The bounding box is used for giving drag & drop feedback.
Move selected objects within the model of c from the origin given by source frame src and point (sx, sy) to the target given by destination frame dst and point (dx, dy). Since this is a move of material within a single model, there is no need for conversions, and the most "natural" moving semantics can be provided.
Copy selected objects within the model of c from the origin given by source frame src and point (sx, sy) to the target given by destination frame dst and point (dx, dy). Since this is a copy of material within a single model, there is no need for conversions, and the most "natural" copying semantics can be provided.
PROCEDURE (c: Controller) SelectionCopy (): Model
Interface
Return a copy of the selected objects, encapsulated in the returned model.
Paste a native model into the model of c as displayed in frame f. Since the model is native, it is to be merged into the model of c rather than wrapped into a view and embedded.
Interpret the arrow character ch, i.e. one out of the following list. The interpretation is to be modified as requested by units and select. The standard interpretation of arrow characters is the modification of the current selection or the moving of the insertion point. Modifying or moving in larger units (e.g. words instead of characters) is requested by units. Establishment of a selection if requested by select.
Some controllers may ignore one or the other request, e.g. may not distinguish units of varying granularity or may not support selections.
Table of arrow characters:
The intention is a modification or move in the indicated direction on the smallest supported granularity ("arrow"), on the basis of "pages" as defined by the size of frame f, or on the basis of the whole "document", i.e. the far extremes of the model of c. The precise interpretation of the directions and units is left to the specific controller.
Paste view v with desired size (w, h) into the model of c.
(Typically, a controller delegates this request to its model which implements the request by using Properties.PreferredSize to negotiate the new size with v.)
Return whether the controller currently has a selection. By default, only singleton selections are supported. To be extended to include intrinsic selections.
c.ThisModel() # NIL 20
PROCEDURE (c: Controller) Selectable (): BOOLEAN
Interface
Return whether the controller could establish a non
empty selection. If something (or everything) is already selected, this is considered selectable.
Set the controller's selection to a singleton selection covering view s. IF s = NIL, the current singleton selection is cleared. Needs to be extended to adjust intrinsic selection state accordingly.
Set the selection to its maximum extent, i.e. select all intrinsic content of the controller's model plus all embedded views. For an empty model there is no visible result; for a model with only one embedded view and no intrinsic contents a singleton selection results.
Depending on show, show or hide the selection's visual marking. The default handles singleton selections only. To be replaced to include intrinsic selections.
Calls Mark to show all marks in (l, t, r, b), then, if no subfocus exists and c.opts indicates mask mode, tries to establish a subfocus: the first embedded view that wants to claim the focus (Properties.FocusPref.setFocus) gets it. If the new subfocus wants to start off with an initially selected contents (Properties.FocusPref.selectOnFocus), it is also fully selected.
PROCEDURE (c: Controller) Neutralize
Default
Remove all modal marks, including focus, selection, and caret. The default handles focus and selection. To be extended to handle caret and possibly further marks.
Except for performance, the default is equivalent to:
The default is to handle Properties.SetMsg and Properties.PollMsg by splitting the handling of native and embedded properties and set or return the combined property list. Also, unless noSelection, noFocus, and noCaret are set in c.opts, field Properties.FocusPref.setFocus is set.